package io.geekidea.boot.util.dingtalk;

import cn.hutool.http.HttpStatus;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson2.JSON;
import com.aliyun.dingtalkstorage_1_0.models.AddFolderResponse;
import com.aliyun.dingtalkstorage_1_0.models.AddFolderResponseBody.AddFolderResponseBodyDentry;
import com.aliyun.dingtalkstorage_1_0.models.CommitFileResponse;
import com.aliyun.dingtalkstorage_1_0.models.CommitFileResponseBody.CommitFileResponseBodyDentry;
import com.aliyun.dingtalkstorage_1_0.models.GetDentryOpenInfoResponse;
import com.aliyun.dingtalkstorage_1_0.models.GetDentryOpenInfoResponseBody;
import com.aliyun.dingtalkstorage_1_0.models.GetDentryResponse;
import com.aliyun.dingtalkstorage_1_0.models.GetDentryResponseBody.GetDentryResponseBodyDentry;
import com.aliyun.dingtalkstorage_1_0.models.GetFileDownloadInfoResponse;
import com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosResponse;
import com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosResponseBody;
import com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosResponseBody.GetMultipartFileUploadInfosResponseBodyMultipartHeaderSignatureInfos;
import com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadResponse;
import com.aliyun.dingtalkstorage_1_0.models.ListAllDentriesResponse;
import com.aliyun.dingtalkstorage_1_0.models.ListAllDentriesResponseBody;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DingStorageUtil {


  private static com.aliyun.dingtalkstorage_1_0.Client createClient() throws Exception {
    Config config = new Config();
    config.protocol = "https";
    config.regionId = "central";
    return new com.aliyun.dingtalkstorage_1_0.Client(config);
  }


  /**
   * https://open.dingtalk.com/document/orgapp/obtain-file-or-folder-information
   *
   * @param accessToken
   * @param spaceId
   * @param dentryId
   * @param unionId
   * @return
   */
  public static GetDentryResponseBodyDentry folderDetail(String accessToken, String spaceId,
      String dentryId,
      String unionId) {
    com.aliyun.dingtalkstorage_1_0.Client client = null;
    try {
      client = DingStorageUtil.createClient();
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
      return null;
    }

    com.aliyun.dingtalkstorage_1_0.models.GetDentryHeaders getDentryHeaders = new com.aliyun.dingtalkstorage_1_0.models.GetDentryHeaders();
    getDentryHeaders.xAcsDingtalkAccessToken = accessToken;
    com.aliyun.dingtalkstorage_1_0.models.GetDentryRequest.GetDentryRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.GetDentryRequest.GetDentryRequestOption();
    com.aliyun.dingtalkstorage_1_0.models.GetDentryRequest getDentryRequest = new com.aliyun.dingtalkstorage_1_0.models.GetDentryRequest()
        .setUnionId(unionId)
        .setOption(option);
    try {
      log.debug("folderDetail request {}", JSON.toJSONString(getDentryRequest));
      GetDentryResponse resp = client.getDentryWithOptions(spaceId, dentryId,
          getDentryRequest, getDentryHeaders,
          new RuntimeOptions());
      log.debug("folderDetail resp {}", JSON.toJSONString(resp));
      if (resp.getStatusCode() == HttpStatus.HTTP_OK) {
        return resp.getBody().getDentry();
      }
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
    }
    return null;
  }

  /**
   * https://open.dingtalk.com/document/orgapp/add-folder
   *
   * @param accessToken
   * @param spaceId
   * @param parentId
   * @param name
   * @param unionId
   * @return
   * @throws Exception
   */
  public static AddFolderResponseBodyDentry createFolder(String accessToken, String spaceId,
      String parentId,
      String name,
      String unionId) {
    com.aliyun.dingtalkstorage_1_0.Client client = null;
    try {
      client = DingStorageUtil.createClient();
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
      return null;
    }

    com.aliyun.dingtalkstorage_1_0.models.AddFolderHeaders addFolderHeaders = new com.aliyun.dingtalkstorage_1_0.models.AddFolderHeaders();
    addFolderHeaders.xAcsDingtalkAccessToken = accessToken;

    com.aliyun.dingtalkstorage_1_0.models.AddFolderRequest.AddFolderRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.AddFolderRequest.AddFolderRequestOption()
        .setConflictStrategy("RETURN_DENTRY_IF_EXISTS");// 返回已存在文件夹

    com.aliyun.dingtalkstorage_1_0.models.AddFolderRequest addFolderRequest = new com.aliyun.dingtalkstorage_1_0.models.AddFolderRequest()
        .setUnionId(unionId)
        .setName(name)
        .setOption(option);
    try {
      AddFolderResponse resp = client.addFolderWithOptions(spaceId, parentId, addFolderRequest,
          addFolderHeaders,
          new com.aliyun.teautil.models.RuntimeOptions());
      if (resp.getStatusCode() == HttpStatus.HTTP_OK) {
        return resp.getBody().getDentry();
      }
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
    }
    return null;
  }

  /**
   * https://open.dingtalk.com/document/orgapp/initialize-a-multipart-upload-object
   *
   * @param accessToken
   * @param parentId
   * @param spaceId
   * @param fileName
   * @param unionId
   * @return
   * @throws Exception
   */
  public static String getMultipartUploadKey(String accessToken, String parentId, String spaceId,
      String fileName, long fileSize, String fileMd5, String unionId) {
    com.aliyun.dingtalkstorage_1_0.Client client = null;
    try {
      client = DingStorageUtil.createClient();
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
      return null;
    }

    com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadHeaders initMultipartFileUploadHeaders = new com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadHeaders();
    initMultipartFileUploadHeaders.xAcsDingtalkAccessToken = accessToken;
    com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadRequest.InitMultipartFileUploadRequestOptionPreCheckParam optionPreCheckParam = new com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadRequest.InitMultipartFileUploadRequestOptionPreCheckParam()
        .setMd5(fileMd5)
        .setSize(fileSize)
        .setParentId(parentId)
        .setName(fileName);
    com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadRequest.InitMultipartFileUploadRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadRequest.InitMultipartFileUploadRequestOption()
        .setStorageDriver("DINGTALK")
        .setPreCheckParam(optionPreCheckParam)
        .setPreferRegion("ZHANGJIAKOU");
    com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadRequest initMultipartFileUploadRequest = new com.aliyun.dingtalkstorage_1_0.models.InitMultipartFileUploadRequest()
        .setUnionId(unionId)
        .setOption(option);
    try {
      log.debug("getMultipartUploadKey request {}",
          JSON.toJSONString(initMultipartFileUploadRequest));
      InitMultipartFileUploadResponse resp = client.initMultipartFileUploadWithOptions(spaceId,
          initMultipartFileUploadRequest,
          initMultipartFileUploadHeaders, new com.aliyun.teautil.models.RuntimeOptions());
      log.debug("getMultipartUploadKey resp {}", JSON.toJSONString(resp));
      if (resp.getStatusCode() == HttpStatus.HTTP_OK) {
        return resp.getBody().getUploadKey();
      }
    } catch (Exception e) {
      log.error("请求：{} 错误消息：{}", JSON.toJSONString(initMultipartFileUploadRequest),
          e.getMessage(), e);
    }
    return null;
  }

  public static List<GetMultipartFileUploadInfosResponseBodyMultipartHeaderSignatureInfos> getMultipartDetail(
      String accessToken, String uploadKey,
      List<Integer> partNumbers, String unionId) {
    com.aliyun.dingtalkstorage_1_0.Client client = null;
    try {
      client = DingStorageUtil.createClient();
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
      return null;
    }
    com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosHeaders getMultipartFileUploadInfosHeaders = new com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosHeaders();
    getMultipartFileUploadInfosHeaders.xAcsDingtalkAccessToken = accessToken;
    com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosRequest.GetMultipartFileUploadInfosRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosRequest.GetMultipartFileUploadInfosRequestOption()
        .setPreferIntranet(false);
    com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosRequest getMultipartFileUploadInfosRequest = new com.aliyun.dingtalkstorage_1_0.models.GetMultipartFileUploadInfosRequest()
        .setUnionId(unionId)
        .setUploadKey(uploadKey)
        .setPartNumbers(partNumbers)
        .setOption(option);
    try {
      GetMultipartFileUploadInfosResponse resp = client.getMultipartFileUploadInfosWithOptions(
          getMultipartFileUploadInfosRequest,
          getMultipartFileUploadInfosHeaders, new com.aliyun.teautil.models.RuntimeOptions());
      if (resp.getStatusCode() == HttpStatus.HTTP_OK) {
        return resp.getBody().getMultipartHeaderSignatureInfos();
      }
    } catch (Exception e) {
      log.error("请求：{} 错误消息：{}", JSON.toJSONString(getMultipartFileUploadInfosRequest),
          e.getMessage(), e);
    }
    return null;
  }

  public static boolean uploadPartFile(long start, long size,
      GetMultipartFileUploadInfosResponseBody.GetMultipartFileUploadInfosResponseBodyMultipartHeaderSignatureInfosHeaderSignatureInfo headerSignatureInfo,
      File file) {
    try {
      InputStream inputStream = Files.newInputStream(file.toPath());
      if (start > 0) {
        inputStream.skip(start);
      }

      URL url = new URL(headerSignatureInfo.getResourceUrls().get(0));
//      URL url = new URL("https://" + headerSignatureInfo.getInternalResourceUrls().get(0));
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setDoOutput(true);
      connection.setRequestMethod("PUT");
      connection.setUseCaches(false);
      if (headerSignatureInfo.getHeaders() != null) {
        for (Map.Entry<String, String> entry : headerSignatureInfo.getHeaders().entrySet()) {
          connection.setRequestProperty(entry.getKey(), entry.getValue());
        }
      }
      connection.setReadTimeout(10 * 1000);
      connection.setConnectTimeout(10 * 1000);
      connection.connect();

      OutputStream out = connection.getOutputStream();
      byte[] buffer = new byte[1024];
      long remain = size;
      while (remain > 0) {
        int sizeToRead = remain < buffer.length ? (int) remain : buffer.length;
        int rsz = inputStream.read(buffer, 0, sizeToRead);
        if (rsz < 0) {
          break;
        }
        out.write(buffer, 0, rsz);
        remain -= rsz;
      }
      out.flush();
      out.close();

//      String responseMessage = connection.getResponseMessage();

      int responseCode = connection.getResponseCode();

//      for (Entry<String, List<String>> entry : connection.getHeaderFields().entrySet()) {
//        log.debug("请求头消息：{} {}", entry.getKey(), entry.getValue());
//      }

      connection.disconnect();
      if (responseCode == HttpStatus.HTTP_OK) {
        return true;
      }
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
    }
    return false;
  }

  /**
   * https://open.dingtalk.com/document/orgapp/submittal-file
   *
   * @param accessToken
   * @param spaceId
   * @param uploadKey
   * @param fileName
   * @param fileSize
   * @param unionId
   * @return
   */
  public static CommitFileResponseBodyDentry submittalFile(String accessToken, String spaceId,
      String parentId,
      String uploadKey,
      String fileName,
      Long fileSize, String conflictStrategy, String unionId) {
    com.aliyun.dingtalkstorage_1_0.Client client = null;
    try {
      com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
      config.protocol = "https";
      config.regionId = "central";
      client = DingStorageUtil.createClient();
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
      return null;
    }
    com.aliyun.dingtalkstorage_1_0.models.CommitFileHeaders commitFileHeaders = new com.aliyun.dingtalkstorage_1_0.models.CommitFileHeaders();
    commitFileHeaders.xAcsDingtalkAccessToken = accessToken;
    com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest.CommitFileRequestOptionAppProperties optionAppProperties0 = new com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest.CommitFileRequestOptionAppProperties();

    com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest.CommitFileRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest.CommitFileRequestOption()
        .setSize(fileSize)
        .setConflictStrategy("AUTO_RENAME");

    com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest commitFileRequest = new com.aliyun.dingtalkstorage_1_0.models.CommitFileRequest()
        .setUnionId(unionId)
        .setUploadKey(uploadKey)
        .setName(fileName)
        .setParentId(parentId)
        .setOption(option);
    try {
      CommitFileResponse resp = client.commitFileWithOptions(spaceId, commitFileRequest,
          commitFileHeaders, new com.aliyun.teautil.models.RuntimeOptions());
      if (resp.getStatusCode() == HttpStatus.HTTP_OK) {
        return resp.getBody().getDentry();
      }
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
    }
    return null;
  }

  /**
   * https://open.dingtalk.com/document/orgapp/get-a-list-of-all-files-or-folders-under-a
   *
   * @param accessToken
   * @param spaceId
   * @param unionId
   * @return
   */
  public static ListAllDentriesResponseBody getAllDentries(String accessToken,
      String spaceId, String unionId, String nextToken) {

    com.aliyun.dingtalkstorage_1_0.Client client = null;
    try {
      client = DingStorageUtil.createClient();
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
      return null;
    }

    com.aliyun.dingtalkstorage_1_0.models.ListAllDentriesHeaders listAllDentriesHeaders = new com.aliyun.dingtalkstorage_1_0.models.ListAllDentriesHeaders();
    listAllDentriesHeaders.xAcsDingtalkAccessToken = accessToken;
    com.aliyun.dingtalkstorage_1_0.models.ListAllDentriesRequest.ListAllDentriesRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.ListAllDentriesRequest.ListAllDentriesRequestOption()
        .setMaxResults(50)
        .setOrder("DESC");

    if (StringUtils.isNotBlank(nextToken)) {
      option.setNextToken(nextToken);
    }

    com.aliyun.dingtalkstorage_1_0.models.ListAllDentriesRequest listAllDentriesRequest = new com.aliyun.dingtalkstorage_1_0.models.ListAllDentriesRequest()
        .setUnionId(unionId)
        .setOption(option);

    try {
      ListAllDentriesResponse resp = client.listAllDentriesWithOptions(spaceId,
          listAllDentriesRequest, listAllDentriesHeaders,
          new com.aliyun.teautil.models.RuntimeOptions());

      if (resp.getStatusCode() == HttpStatus.HTTP_OK) {
        return resp.getBody();
      }
    } catch (Exception e) {
      log.error("请求：{} 错误消息：{}", JSON.toJSONString(listAllDentriesRequest), e.getMessage(),
          e);
    }
    return null;
  }

  /**
   * https://open.dingtalk.com/document/orgapp/obtains-the-download-information-about-a-file
   *
   * @param accessToken
   * @param spaceId
   * @param dentryId
   * @param unionId
   * @return
   */
  public static GetFileDownloadInfoResponse getDownloadInfo(
      String accessToken,
      String spaceId, String dentryId,
      String unionId) {
    com.aliyun.dingtalkstorage_1_0.Client client = null;
    try {
      client = DingStorageUtil.createClient();
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
      return null;
    }

    com.aliyun.dingtalkstorage_1_0.models.GetFileDownloadInfoHeaders getFileDownloadInfoHeaders = new com.aliyun.dingtalkstorage_1_0.models.GetFileDownloadInfoHeaders();
    getFileDownloadInfoHeaders.xAcsDingtalkAccessToken = accessToken;
    com.aliyun.dingtalkstorage_1_0.models.GetFileDownloadInfoRequest.GetFileDownloadInfoRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.GetFileDownloadInfoRequest.GetFileDownloadInfoRequestOption();
//        .setVersion(1L)
//        .setPreferIntranet(false);
    com.aliyun.dingtalkstorage_1_0.models.GetFileDownloadInfoRequest getFileDownloadInfoRequest = new com.aliyun.dingtalkstorage_1_0.models.GetFileDownloadInfoRequest()
        .setUnionId(unionId)
//        .setUnionId("3fK9JGtcaupN7UyLLKVVMAiEiE")
        .setOption(option);
    try {
      GetFileDownloadInfoResponse fileDownloadInfoWithOptions = client.getFileDownloadInfoWithOptions(
          spaceId, dentryId,
          getFileDownloadInfoRequest,
          getFileDownloadInfoHeaders, new RuntimeOptions());
      return fileDownloadInfoWithOptions;
    } catch (Exception e) {
      log.error("请求：{} 错误消息：{}", JSON.toJSONString(getFileDownloadInfoRequest),
          e.getMessage(), e);

//      TeaException err = new TeaException(e.getMessage(), e);
//      if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(
//          err.message)) {
//        // err 中含有 code 和 message 属性，可帮助开发定位问题
//        if (err.code.equals("403")) {
//          GetFileDownloadInfoResponse getFileDownloadInfoResponse = new GetFileDownloadInfoResponse();
//          getFileDownloadInfoResponse.setStatusCode(HttpStatus.HTTP_FORBIDDEN);
//          return getFileDownloadInfoResponse;
//        }
//      }
    }
    return null;
  }

  /**
   * https://open.dingtalk.com/document/orgapp/obtains-the-object-preview-or-editing-information
   *
   * @param accessToken
   * @param spaceId
   * @param dentryId
   * @param unionId
   * @return
   */
  public static GetDentryOpenInfoResponseBody getFileUrlInfo(
      String accessToken,
      String spaceId, String dentryId,
      String unionId) {
    com.aliyun.dingtalkstorage_1_0.Client client = null;
    try {
      client = DingStorageUtil.createClient();
    } catch (Exception e) {
      log.error("错误消息：{}", e.getMessage(), e);
      return null;
    }

    com.aliyun.dingtalkstorage_1_0.models.GetDentryOpenInfoHeaders getDentryOpenInfoHeaders = new com.aliyun.dingtalkstorage_1_0.models.GetDentryOpenInfoHeaders();
    getDentryOpenInfoHeaders.xAcsDingtalkAccessToken = accessToken;
    com.aliyun.dingtalkstorage_1_0.models.GetDentryOpenInfoRequest.GetDentryOpenInfoRequestOption option = new com.aliyun.dingtalkstorage_1_0.models.GetDentryOpenInfoRequest.GetDentryOpenInfoRequestOption()
        .setType("PREVIEW")
        .setCheckLogin(true);
    com.aliyun.dingtalkstorage_1_0.models.GetDentryOpenInfoRequest getDentryOpenInfoRequest = new com.aliyun.dingtalkstorage_1_0.models.GetDentryOpenInfoRequest()
        .setUnionId(unionId)
        .setOption(option);
    try {
      GetDentryOpenInfoResponse resp = client.getDentryOpenInfoWithOptions(
          spaceId, dentryId, getDentryOpenInfoRequest, getDentryOpenInfoHeaders,
          new RuntimeOptions());
      if (resp.getStatusCode() == HttpStatus.HTTP_OK) {
        return resp.getBody();
      }
    } catch (Exception e) {
      log.error("请求：{} 错误消息：{}", JSON.toJSONString(getDentryOpenInfoRequest),
          e.getMessage(), e);
    }
    return null;
  }

}
